﻿
namespace Huirui.Cavan.Core.Extension
{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics.Contracts;
    using System.IO;
    using System.Linq;
    using System.Runtime.Serialization.Formatters.Binary;
    using System.Web.Mvc;
    using Huirui.Cavan.Core.Persistent;

    /// <summary>
    ///     Extensions available on every place of the framework.
    /// </summary>
    public static partial class Ext
    {
        #region byte compare
        static readonly BinaryFormatter BinaryFormatter = new BinaryFormatter();

        /// <summary>
        ///     Compares two byte[] arrays if they contain same bytes
        /// </summary>
        /// <param name = "array">if null false is returned</param>
        /// <param name = "toCompare">if null false is returned</param>
        /// <returns>true if both byte arrays contains same bytes</returns>
        public static bool Compare(this byte[] array, byte[] toCompare)
        {
            if (array.Is()
                &&
                toCompare.Is())
            {
                if (array.Length
                    ==
                    toCompare.Length)
                {
                    var i = 0;
                    while ((i < array.Length)
                           && (array[i] == toCompare[i]))
                    {
                        i++;
                    }
                    if (i == array.Length)
                    {
                        return true;
                    }
                }
            }
            return false;
        }

        /// <summary>
        ///     Compares two serializable objects.
        ///     Converts them into byte[] array using BinaryFormatter 
        ///     and than compares these byte[] arrays
        /// </summary>
        /// <param name = "value"></param>
        /// <param name = "toCompare"></param>
        /// <returns></returns>
        public static bool ByteCompare(this object value, object toCompare)
        {
            var msObj = new MemoryStream();
            var msToCompare = new MemoryStream();

            BinaryFormatter.Serialize(msObj, value);
            BinaryFormatter.Serialize(msToCompare, toCompare);

            return msObj.ToArray().Compare(msToCompare.ToArray());
        }

        /// <summary>
        ///     Uses the MemoryStream to convert provided value into the byte array
        /// </summary>
        /// <param name = "value"></param>
        /// <returns></returns>
        public static byte[] ToByteArray(this IPersistentObject value)
        {
            return GetByteArray(value);
        }

        /// <summary>
        ///     Uses the MemoryStream to convert provided value into the byte array
        /// </summary>
        /// <param name = "value"></param>
        /// <returns></returns>
        public static byte[] ToByteArray(this ISearch value)
        {
            return GetByteArray(value);
        }

        /// <summary>
        ///     Uses the MemoryStream to convert provided value into the byte array
        /// </summary>
        /// <param name = "controller"></param>
        /// <param name = "value"></param>
        /// <returns></returns>
        public static byte[] ToByteArray(this ControllerContext controller, object value)
        {
            return GetByteArray(value);
        }

        /// <summary>
        ///     Uses the MemoryStream to convert provided value into the byte array
        /// </summary>
        /// <param name = "value"></param>
        /// <returns></returns>
        static byte[] GetByteArray(object value)
        {
            var ms = new MemoryStream();
            BinaryFormatter.Serialize(ms, value);
            return ms.ToArray();
        }
        #endregion byte compare
    }
}